#include <stdlib.h>
#include <stdio.h>
#include <nds.h>

#include <string.h>
#include <errno.h>
#include <xwm.h>
#include <sys/stat.h>
#ifdef NITRO
#    include <filesystem.h>
#else
#    include <fat.h>
#endif

// common headers
#include "common.h"

// local headers
#include "binarylist.h"
#include "interrupts.h"
#include "library.h"
#include "plugin.h"
#include "sellist.h"
#include "video.h"
#include "slibs.h"
#include "guru.h"
#include "filelist.h"
#include "sound.h"
#include "directories.h"
#include "languages.h"

#include "main.h"

int main(int argc, char *argv[]) {
    interruptsInit();   // init the interrupts
    videoInit();        // init the video
    slibsInit();        // init the pointers in the struct we pass to the binaries
    guruInit();         // init the exception handler
    soundInit();        // init maxmod

    iprintf("Welcome in SunOS v0.1a private");

#if defined(NITRO)
    iprintf("\nnitroFS release");

    if(!nitroFSInit()) {
        iprintf("\nnitroFS init failed");
        iprintf("\nargc=%d", argc);
        int i;
        for(i=0; i<argc; i++) iprintf("\n argv[%d]=\"%s\"", i, argv[i]);
        while(1) swiWaitForVBlank();
    }
#else
    if(!fatInitDefault()) {
        iprintf("\nfatFS init failed");
        while(1) swiWaitForVBlank();
    }
#endif

    dirsInit(); // check/create default dirs

    iprintf("\nFree:%dB", getMemFree());

{
    char label[12];
    void fatGetVolumeLabel (const char* name, char *label);
    fatGetVolumeLabel("fat:/", label);
    iprintf("\nSD name : \'%s\'", label);
}

#if 0
{ iprintf("\nfl_getcwd() test {\n");
    sFile *fl, *cur;
    #if defined(NITRO)
    chdir("/tests/tCONFIG");
    #endif

    fl=fl_readcwd(FL_STAT);
    if(fl) {
        fl_sort(fl, BY_SIZE | DIRS_BEFORE | INVERT);
        cur=fl;
        while(cur) {
            if(S_ISREG(cur->st.st_mode)) iprintf("{%d:%s:%d}", (int)cur->st.st_mtime, cur->name, (int)cur->st.st_size);
            else iprintf("[%d:%s]", (int)cur->st.st_mtime, cur->name);
            cur=cur->next;
        }

        iprintf("\n\n");

        fl_sort(fl, BY_NAME | DIRS_BEFORE);
        cur=fl;
        while(cur) {
            if(S_ISREG(cur->st.st_mode)) iprintf("{%s}", cur->name);
            else iprintf("[%s]", cur->name);
            cur=cur->next;
        }

        fl_free(fl);
    }
    else printf(">:( (%d(%s))", errno, strerror(errno));

    while(!(keysDown() & KEY_B)) swiWaitForVBlank();
iprintf("\n}"); }
#endif

    LLIST *liblist=NULL;
    LLIST *pluglist=NULL;

    iprintf("\nCreating lists...");
    if(initLists(&liblist, &pluglist)) {
        iprintf("failed");
        return 1;
    }
    iprintf("ok");

    if(liblist) {
        iprintf("\nFound %d libraries :", ll_get_num_el(liblist));
        LLIST *cur=liblist;
        while(cur) {
            iprintf("\n 0x%08x:%s", SL(cur)->id, SL(cur)->name);
            cur=cur->next;
        }
    }

    if(pluglist) {
        iprintf("\nFound %d plugins", ll_get_num_el(pluglist));
    }
    else {
            iprintf("\nERROR: no plugin found");
            while(1) swiWaitForVBlank();
    }

#if 0
{ iprintf("\ngetLibraryByFileType() test {");
    sLibrary *lib;

    lib=getLibraryByFileType("/conf", tCONFIG);
    if(lib) iprintf("\nlib->name=%s", lib->name);
    else iprintf("\n!lib");

    lib=getLibraryByFileType("/test", tSOUND);
    if(lib) iprintf("\nlib->name=%s", lib->name);
    else iprintf("\n!lib");
iprintf("\n}"); }
#endif

#if 0
{ iprintf("\nlanguage test {");
    chdir("/data/SunOS/languages");

    sFile *fl=fl_getcwd(FL_STAT);
    sI18nLang lng;
    bzero(&lng, sizeof(sI18nLang));

    #define TXT_SUNOS_DESC 0
    #define TXT_SUNOS_BAD 5
    #define _(t) i18n_get(&lng, "General", (t))

    if(!i18n_initLang(&lng, fl, "fr")) {
        iprintf("\nSunOS description : %s", _(TXT_SUNOS_DESC));
        iprintf("\nWhat's bad in SunOS : %s", _(TXT_SUNOS_BAD));

        i18n_deinitLang(&lng);
    }
    else iprintf("\nfr failed !");

    if(!i18n_initLang(&lng, fl, "en")) {
        iprintf("\nSunOS description : %s", _(TXT_SUNOS_DESC));
        iprintf("\nWhat's bad in SunOS : %s", _(TXT_SUNOS_BAD));

        i18n_deinitLang(&lng);
    }
    else iprintf("\nen failed !");

    fl_free(fl);

    while(!(keysDown() & KEY_B)) swiWaitForVBlank();
iprintf("\n}"); }
#endif

    LLIST *plug=pluglist;
    while(1) {  // Main loop
iprintf("\nFree:%dB", getMemFree());        // print free memory
void print_stats();
print_stats();                              // print memory usage
iprintf("\nSP=%#x", (unsigned int)getSP()); // print stack pointer

        iprintf("\nChoose a plugin to load :");
        plug=choosePlugin(plug);
        if(!plug) {
            iprintf("\nERROR: no plugin selected");
            plug=pluglist;
            continue;
        }

        runPlugin(SP(plug), 0, NULL);
    }

    return 0;
}

